package com.gcloud.mesh.asset.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Repository;

import com.gcloud.framework.db.PageResult;
import com.gcloud.framework.db.dao.impl.JdbcBaseDaoImpl;
import com.gcloud.mesh.asset.entity.IaasEntity;
import com.gcloud.mesh.asset.enums.AuthorityDeviceType;
import com.gcloud.mesh.asset.enums.DeviceType;
import com.gcloud.mesh.dcs.service.AuthorityService;
import com.gcloud.mesh.header.enums.AuthorityResourceClassification;
import com.gcloud.mesh.header.enums.AuthorityResourceType;
import com.gcloud.mesh.header.enums.ResourceSourceType;
import com.gcloud.mesh.header.msg.dcs.ListByClassificationMsg;
import com.gcloud.mesh.header.vo.analysis.FitterResourceVo;
import com.gcloud.mesh.header.vo.asset.DeviceItemVo;
import com.gcloud.mesh.header.vo.asset.NodeItemVo;
import com.gcloud.mesh.header.vo.dcs.AuthorityVo;
import com.gcloud.mesh.utils.PageUtil;

import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Repository
public class IaasDao extends JdbcBaseDaoImpl<IaasEntity, String>{
	
	@Autowired
	private AuthorityService authorityService;

	public IaasEntity getById(String id, String userId) {
		StringBuffer sql = new StringBuffer();
		sql.append(" select * from asset_iaas");
		sql.append(" where 1 = 1");
	    Map<String, Object> props = new HashMap<String, Object>();
		if(StringUtils.isNotEmpty(id)) {	
			props.put("id", id);
		}
		if(StringUtils.isNotEmpty(userId)) {
			props.put("creator", userId);
		}
		return this.findUniqueByProperties(props);
	}
	
	public <E> PageResult<E> page(int pageNum, int pageSize, String datacenterId, String name, Integer type, String userId, Class<E> clazz) {
		StringBuffer sql = new StringBuffer();
//		sql.append(" select i.* from asset_iaas i");
		// 此处查询建立的索引，忽随意改动字段顺序或增加字段
		sql.append("select i.create_time, i.type, i.name, i.esn, i.device_id, i.device_model, i.device_manufacturer, i.datacenter_id, i.from, i.visible, i.id from asset_iaas i ");
		sql.append(" where 1 = 1");
		sql.append(" and visible = 1 ");
		
		List<Object> values = new ArrayList<Object>();
		if(StringUtils.isNotEmpty(userId)) {
			sql.append(" and i.creator = ?");
			values.add(userId);
		}
		if(type != null && DeviceType.getDeviceTypeByNo(type) != null) {
			
			// 指标监控列表屏蔽机柜
			if (type == -1){
				sql.append(" and i.type != 5");
			}
			else{
				sql.append(" and i.type = ?");
				values.add(type);
			}
		}
		if(StringUtils.isNotEmpty(name)) {
			sql.append(" and i.name like concat('%', ?, '%')");
			values.add(name);
		}
		if(StringUtils.isNotEmpty(datacenterId)) {
			sql.append(" and i.datacenter_id = ?" );
			values.add(datacenterId);
		}
		//排除服务器和交换机
		sql.append(" and i.type in (1, 2, 5, 8) ");
		
//		checkResourceAuthority(sql, AuthorityResourceClassification.IAAS.getName());
		
		sql.append(" order by i.create_time desc");
		
		return this.findBySql(sql.toString(), values, pageNum, pageSize, clazz);	
		
	}
	
	//软分页
	public PageResult<DeviceItemVo> pageDevice(int pageNum, int pageSize, String datacenterId, String name, Integer type) {

		PageResult<DeviceItemVo> res = null;	

		List<AuthorityVo> authorities = listAuthority(AuthorityResourceClassification.IAAS.getName());
		List<String> filterAuthorities = authorities.stream()
				.filter( s -> !s.getEnabled())
				.map( s -> s.getId())
				.collect(Collectors.toList());
		
		List<Integer> types = new ArrayList<Integer>();
		if(type == null) {
			types.add(DeviceType.AIR_CONDITION.getNo());
			types.add(DeviceType.UPS.getNo());
			types.add(DeviceType.DISTRIBUTION_BOX.getNo());
		}else {
			types.add(type);
		}
		
		List<DeviceItemVo> devices = listDevice(datacenterId, name, types);
		List<DeviceItemVo> filterDevices = devices.stream()
				.parallel()
				.filter( s -> {
					String id = DeviceType.getDeviceTypeByNo(s.getType()).getName();
					if(ResourceSourceType.SYNC.getName().equals(s.getFrom()) && filterAuthorities.contains(id)) {
						return false;
					}
					return true;
				})
				.collect(Collectors.toList());
		
		//程序分页
		res = PageUtil.page(pageNum, pageSize, filterDevices);
	

		return res;
		
	}
	
	public <E> PageResult<E> pageNodeAndSwitcher(int pageNum, int pageSize, String name, String userId, Class<E> clazz) {
		StringBuffer sql = new StringBuffer();
		sql.append(" select i.*, d.name datacenter_name from asset_iaas i");
		sql.append(" left join asset_datacenters d on i.datacenter_id = d.id");
		sql.append(" where 1 = 1");
		sql.append(" and i.type in (6, 7)");
		
		List<Object> values = new ArrayList<Object>();
		if(StringUtils.isNotEmpty(userId)) {
			sql.append(" and i.creator = ?");
			values.add(userId);
		}
		if(StringUtils.isNotEmpty(name)) {
			sql.append(" and i.name like concat('%', ?, '%')");
			values.add(name);
		}
		
		checkResourceAuthority(sql, AuthorityResourceClassification.IT_DEVICE.getName());
		
		sql.append(" order by i.create_time desc");
		
		return this.findBySql(sql.toString(), values, pageNum, pageSize, clazz);	
		
	}
	
	public PageResult<DeviceItemVo> pageItDevice(int pageNum, int pageSize, String datacenterId, String name, Integer type) {
		
		List<AuthorityVo> authorities = listAuthority(AuthorityResourceClassification.IT_DEVICE.getName());
		List<String> filterAuthorities = authorities.stream()
				.filter( s -> !s.getEnabled())
				.map( s -> s.getId())
				.collect(Collectors.toList());
		
		List<Integer> types = new ArrayList<Integer>();
		
		if(type == null) {
			types.add(DeviceType.SERVER.getNo());
			types.add(DeviceType.SWITCHER.getNo());
		}else {
			types.add(type);
		}	
		
		List<DeviceItemVo> devices = listDevice(datacenterId, name, types);
		List<DeviceItemVo> filterDevices = devices.stream()
				.filter( s -> {
					String id = DeviceType.getDeviceTypeByNo(s.getType()).getName();
					if(ResourceSourceType.SYNC.getName().equals(s.getFrom()) && filterAuthorities.contains(id)) {
						return false;
					}
					return true;
				})
				.collect(Collectors.toList());
		return PageUtil.page(pageNum, pageSize, filterDevices);	
		
	}
	
	private void checkResourceAuthority(StringBuffer sql, String classification) {

		ListByClassificationMsg msg = new ListByClassificationMsg();
		msg.setClassification(classification);
		List<AuthorityVo> authorities = null;
		try {
			authorities = authorityService.listByClassification(msg);
		}catch(Exception e) {
			log.error("[IaasDao][checkResourceAuthority] AuthorityService服务的listByClassification异常：{}", e.getMessage());
		}
		String template = " and i.type != %d ";
		if (authorities != null) {
			for(AuthorityVo vo: authorities) {
				if(!vo.getEnabled()) {
					int type = AuthorityDeviceType.getByResource(AuthorityResourceType.getByName(vo.getId())).getDevice().getNo();
					sql.append(String.format(template, type));
				}
			}
			
		}
		
		
	}
	
	//包含同步权限判断
	public List<NodeItemVo> listNode(String datacenterId, String userId) {
		
//		List<AuthorityVo> authorities = listAuthority(AuthorityResourceClassification.IT_DEVICE.getName());
//		List<String> filterAuthorities = authorities.stream()
//				.filter( s -> !s.getEnabled())
//				.map( s -> s.getId())
//				.collect(Collectors.toList());
//		
//		List<NodeItemVo> nodes = listNode(datacenterId, userId, NodeItemVo.class);
//		List<NodeItemVo> filterNodes = nodes.stream()
//				.filter( s -> {
//					String id = DeviceType.getDeviceTypeByNo(s.getType()).getName();
//					if(ResourceSourceType.SYNC.getName().equals(s.getFrom()) && filterAuthorities.contains(id)) {
//						return false;
//					}
//					return true;
//				})
//				.collect(Collectors.toList());
		return listNode(datacenterId, userId, NodeItemVo.class);	
		
	}
	
	public <E> List<E> listNode(String datacenterId, String userId, Class<E> clazz) {
		StringBuffer sql = new StringBuffer();
		sql.append(" select i.*,n.mgm_ip, n.ipmi_ip, n.ipmi_user, n.ipmi_password, n.network_status, n.power_status, n.hostname, n.rated_power, "
				+ "n.power_consumption, n.energy_efficiency_ratio, n.storage_capacity, n.`isolation`, d.name datacenter_name from asset_iaas i ");
		sql.append(" left join asset_nodes n on i.device_id = n.id");
		sql.append(" left join asset_datacenters d on i.datacenter_id = d.id");
		sql.append(" where 1 = 1");
		sql.append(" and i.type in (6)");
		sql.append(" and i.visible=1");
		
		List<Object> values = new ArrayList<Object>();
		if(StringUtils.isNotEmpty(userId)) {
			sql.append(" and i.creator = ?");
			values.add(userId);
		}
		if(StringUtils.isNotEmpty(datacenterId)) {
			sql.append(" and i.datacenter_id = ?" );
			values.add(datacenterId);
		}
		
//		checkResourceAuthority(sql, AuthorityResourceClassification.IT_DEVICE.getName());
		
		sql.append(" order by i.create_time desc");
		
		return this.findBySql(sql.toString(), values, clazz);	
		
	}
	
	public <E> List<E> listDevice(String datacenterId, Integer type, String userId, Class<E> clazz) {
		List<Object> values = new ArrayList<Object>();
		StringBuffer sql = new StringBuffer();
		sql.append(" select i.*, d.name datacenter_name from asset_iaas i");
		sql.append(" left join asset_datacenters d on i.datacenter_id = d.id");
		sql.append(" where 1 = 1");
		sql.append(" and visible = 1 ");
		sql.append(" and i.type in (?)");
		values.add(type);
		
		if(StringUtils.isNotEmpty(userId)) {
			sql.append(" and i.creator = ?");
			values.add(userId);
		}
		if(StringUtils.isNotEmpty(datacenterId)) {
			sql.append(" and i.datacenter_id = ?" );
			values.add(datacenterId);
		}
		
//		checkResourceAuthority(sql, AuthorityResourceClassification.IAAS.getName());
		
		sql.append(" order by i.create_time desc");
		
		return this.findBySql(sql.toString(), values, clazz);	
		
	}
	
	public List<DeviceItemVo> listDevice(String datacenterId, Integer type) {
		
		return listDevice(datacenterId, type, null, DeviceItemVo.class);	
		
	}
	
	private List<DeviceItemVo> listDevice(String datacenterId, String name, List<Integer> types) {
		List<Object> values = new ArrayList<Object>();
		StringBuffer sql = new StringBuffer();
//		sql.append(" select i.*, d.name datacenter_name from asset_iaas i");
//		sql.append(" left join asset_datacenters d on i.datacenter_id = d.id");
//		sql.append(" select i.* from asset_iaas i");
		// 此处查询建立的索引，忽随意改动字段顺序或增加字段
		sql.append("select i.create_time, i.type, i.name, i.esn, i.device_id, i.device_model, i.device_manufacturer, i.datacenter_id, i.from, i.id from asset_iaas i ");
		sql.append(" where 1 = 1");	
		
		if(StringUtils.isNotEmpty(name)) {
			sql.append(" and i.name like concat('%', ?, '%')");
			values.add(name);
		}
		if(StringUtils.isNotEmpty(datacenterId)) {
			sql.append(" and i.datacenter_id = ?" );
			values.add(datacenterId);
		}
		
		StringBuffer includeType = new StringBuffer();
		for(Integer i: types) {
			includeType.append(i + ",");
		}
		sql.append(" and i.type in ( " + includeType.substring(0, includeType.length() -1) + " )");
		
		sql.append(" order by i.create_time desc");
		
		List<DeviceItemVo> res = this.findBySql(sql.toString(), values, DeviceItemVo.class);
		
		return res;	
	}
	
	public List<AuthorityVo> listAuthority(String classification) {
		ListByClassificationMsg msg = new ListByClassificationMsg();
		msg.setClassification(classification);
		List<AuthorityVo> authorities = null;
		try {
			authorities = authorityService.listByClassification(msg);
		}catch(Exception e) {
			log.error("[IaasDao][checkResourceAuthority] AuthorityService服务的listByClassification异常：{}", e.getMessage());
		}
		return authorities;
	}
	
	public void updateBatchVisiable(Boolean visable, Integer type) {
		StringBuffer sb = new StringBuffer();
		sb.append("UPDATE asset_iaas i SET ");
		sb.append("i.visible = ");
		sb.append(visable);
		sb.append(" WHERE i.from = 'sync'");
		sb.append(" and type = " + type);
		jdbcTemplate.update(sb.toString());
	}
	
	public List<FitterResourceVo> listFitterResource(String datacenterId) {
		List<Object> values = new ArrayList<Object>();
		StringBuffer sql = new StringBuffer();
		sql.append("select concat_ws(\"_\", i.id, cte.id) resource_id, i.datacenter_id from asset_iaas i");
		sql.append(" left join (select id, datacenter_id from asset_iaas where type=1 and visible=1) cte on i.datacenter_id = cte.datacenter_id ");
		sql.append(" where 1 = 1");
		sql.append(" and i.type=6 ");
		sql.append(" and i.visible=1");
		
		if(StringUtils.isNotEmpty(datacenterId)) {
			sql.append(" and i.datacenter_id = ?" );
			values.add(datacenterId);
		}
		
		return this.findBySql(sql.toString(), values, FitterResourceVo.class);	
		
	}
	
    public List<IaasEntity> findNodeByDatacenterId(String datacenterId){
    	
		StringBuffer sql = new StringBuffer();
		sql.append(" select i.* ");
		sql.append(" from asset_iaas i");
		sql.append(" left join asset_nodes n on i.device_id = n.id" );
		sql.append(" left join asset_datacenters d on i.datacenter_id = d.id");
		sql.append(" where 1 = 1");
		sql.append(" and i.type = 6");
		
		List<Object> values = new ArrayList<Object>();
		if(StringUtils.isNotEmpty(datacenterId)) {
			sql.append(" and i.datacenter_id = ?");
			values.add(datacenterId);
		}
		return findBySql(sql.toString(), values);
    } 
	

}
